一、配置中心对比
目前市面上用的比较多的配置中心有:(按开源时间排序)
Disconf
2014年7月百度开源的配置管理中心,专注于各种「分布式系统配置管理」的「通用组件」和「通用平台」, 提供统一的「配置管理服务」。目前已经不再维护更新。 https://github.com/knightliao/disconf
Spring Cloud Config
2014年9月开源,Spring Cloud 生态组件,可以和Spring Cloud体系无缝整合。 https://github.com/spring-cloud/spring-cloud-config
Apollo
2016年5月,携程开源的配置管理中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实 时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。 https://github.com/ctripcorp/apollo
Nacos
2018年6月,阿里开源的配置中心,也可以做DNS和RPC的服务发现。 https://github.com/alibaba/nacos
1.1 开源技术对比
| 功能点 | Spring Cloud Config | Apollo | Nacos |
|---|---|---|---|
| 配置实时推送 | 支持(Spring Cloud Bus) | 支持(HTTP长轮询1s内) | 支持(HTTP长轮询1s内) |
| 版本管理 | 支持(Git) | 支持 | 支持 |
| 配置回滚 | 支持(Git) | 支持 | 支持 |
| 灰度发布 | 支持 | 支持 | 不支持 |
| 权限管理 | 支持(依赖Git) | 支持 | 不支持 |
| 多集群 | 支持 | 支持 | 支持 |
| 多集群 | 支持 | 支持 | 支持 |
| 多环境 | 支持 | 支持 | 支持 |
| 监听查询 | 支持 | 支持 | 支持 |
| 多语言 | 只支持Java | 主流语言,提供了Open API | 主流语言,提供了Open API |
| 配置格式校验 | 不支持 | 支持 | 支持 |
| 单机读(QPS) | 7(限流所致) | 9000 | 15000 |
| 单击写(QPS) | 5(限流所致) | 1100 | 1800 |
| 3节点读 (QPS) | 21(限流所致) | 27000 | 45000 |
| 3节点写 (QPS) | 5(限流所致) | 3300 | 5600 |
1.2 总结
Apollo和Nacos相对于Spring Cloud Config的生态支持更广,在配置管理流程上做的更好。Apollo相对 于Nacos在配置管理做的更加全面,Nacos则使用起来相对比较简洁,在对性能要求比较高的大规模场景更适合。
性能方面Nacos的读写性能最高,Apollo次之,Spring Cloud Confifig依赖Git场景不适合开 放的大规模自动化运维API。功能方面Apollo最为完善,nacos具有Apollo大部分配置管理功能,而Spring Cloud Confifig不带运维管理界面,需要自行开发。Nacos的一大优势是整合了注册中心、配置中心功能,部署和操作相比 Apollo都要直观简单,因此它简化了架构复杂度,并减轻运维及部署工作。
二、注册中心对比
目前服务发现中心有:Nacos、Eureka、Consul和Zookeeper。
| 对比项目 | Nacos | Eureka | Consul | Zookeeper |
|---|---|---|---|---|
| 一致性协议 | 支持AP和CP模型 | AP模型 | CP模型 | CP模型 |
| 健康检查 | TCP/HTTP/MYSQL/Client Beat | Client Beat | TCP/HTTP/gRPC/Cmd | Keep Alive |
| 负载均衡策略 | 权重/metadata/Selector | Ribbon | Fabio | |
| 雪崩保护 | 有 | 有 | 无 | 无 |
| 自动注销实例 | 支持 | 支持 | 不支持 | 支持 |
| 访问协议 | HTTP/DNS | HTTP | HTTP/DNS | TCP |
| 监听支持 | 支持 | 支持 | 支持 | 支持 |
| 多数据中心 | 支持 | 支持 | 支持 | 不支持 |
| 跨注册中心同步 | 支持 | 不支持 | 支持 | 不支持 |
| SpringCloud集成 | 支持 | 支持 | 支持 | 不支持 |
| Dubbo集成 | 支持 | 不支持 | 不支持 | 支持 |
| k8s集成 | 支持 | 不支持 | 支持 | 不支持 |
三、网关对比
使用较多的网关
Ngnix+lua
使用nginx的反向代理和负载均衡可实现对api服务器的负载均衡及高可用。lua是一种脚本语言,可以来编写一些简单的逻辑, nginx支持lua脚本
Kong
基于Nginx+Lua开发,性能高,稳定,有多个可用的插件(限流、鉴权等等)可以开箱即用。 问题:只支持Http协议;二次开发,自由扩展困难;提供管理API,缺乏更易用的管控、配置方式。
Zuul Netflflix开源的网关,功能丰富,使用JAVA开发,易于二次开发 问题:缺乏管控,无法动态配置;依赖组件较多;处理Http请求依赖的是Web容器,性能不如Nginx
Spring Cloud Gateway
Spring公司为了替换Zuul而开发的网关服务。
四、Mq相关
4.1 AMQP
AMQP是一套公开的消息队列协议,最早在2003年被提出,它旨在从协议层定义消息通信数据的标准格式, 为的就是解决MQ市场上协议不统一的问题。RabbitMQ就是遵循AMQP标准协议开发的MQ服务。 具有跨平台性,服务器供应商,生产者,消费者可以使用不同的语言来实现。
消息种类为byte[]
消息模型:
- direct exchange
- fanout exchange
- topic exchange
- headers exchange
- system exchange
4.2 JMS
JMS是java提供的一套消息服务API标准,其目的是为所有的java应用程序提供统一的消息通信的标准,类似java的 jdbc,只要遵循jms标准的应用程序之间都可以进行消息通信。它和AMQP有什么 不同,jms是java语言专属的消 息服务标准,它是在api层定义标准,并且只能用于java应用;而AMQP是在协议层定义的标准,是跨语言的 。
JMS消息模型
JMS规范中规范了消息有两种模型。分别是点对点模型和发布订阅模型。
JMS消息种类
根据消息中包含的数据种类划分,可以将消息划分成6种消息。
- TextMessage
- MapMessage
- BytesMessage
- StreamMessage
- ObjectMessage
- Message (只有消息头和属性)
4.3 MQTT
MQTT(Message Queueing Telemetry Transport)消息队列遥测传输,专为小设备设计,是物联网(IOT)生态系统中主要成分之一。
4.4 KafKa
Kafka,一种高吞吐量的分布式发布订阅消息系统,提供实时消息功能。Kafka技术并不是作为消息中间件为主要功能的产品,但是其拥有发布订阅的工作模式,也可以充当消息中间件来使用,而且目前企业级开发中其身影也不少见。
4.5 Mq技术对比
几种常见MQ的对比:
| RabbitMQ | ActiveMQ | RocketMQ | Kafka | |
|---|---|---|---|---|
| 公司/社区 | Rabbit | Apache | 阿里 | Apache |
| 开发语言 | Erlang | Java | Java | Scala&Java |
| 协议支持 | AMQP,XMPP,SMTP,STOMP | OpenWire,STOMP,REST,XMPP,AMQP | 自定义协议 | 自定义协议 |
| 可用性 | 高 | 一般 | 高 | 高 |
| 单机吞吐量 | 一般 | 差 | 高 | 非常高 |
| 消息延迟 | 微秒级 | 毫秒级 | 毫秒级 | 毫秒以内 |
| 消息可靠性 | 高 | 一般 | 高 | 一般 |
追求可用性:Kafka、 RocketMQ 、RabbitMQ
追求可靠性:RabbitMQ、RocketMQ
追求吞吐能力:RocketMQ、Kafka
追求消息低延迟:RabbitMQ、Kafka
五、NoSQL
5.1 概述
NoSQL是Not only SQL的缩写,大意为“不只是SQL”,说明这项技术是而非替代。在整个NoSQL技术栈中、、被称为NoSQL三剑客。那么时代为什么需要NoSQL数据库呢?我们来做个对比:
| 关系型数据库 | NoSQL数据库 | |
|---|---|---|
| 数据存储位置 | 硬盘 | 内存 |
| 数据结构 | 高度组织化结构化数据 | 没有预定义的模式 |
| 数据操作方式 | SQL | 所有数据都是键值对,没有声明性查询语言 |
| 事务控制 | 严格的基础事务ACID原则 | CAP定理 |
所以NoSQL数据库的最大优势体现为:高性能、高可用性和可伸缩性。
5.2 NoSQL技术对比
| Tair | Redis | Memcache | Ehcache | |
|---|---|---|---|---|
| 是否开源 | 开源 | 开源 | 开源 | 开源 |
| 使用语言 | 服务器端C++;客户端支持C、JAVA、PHP等 | ANSI C语言编写 ,提供多种语言(C/C++/JAVA/PHP等)的API | 服务端C,客户端支持c、php、java、python等 | java |
| 集群 | 支持 | 3.0以后支持 | 服务端不支持,客户端使用一致性hash算法将数据分布式存储 | 支持,默认是异步同步 |
| 容灾 | 支持 | 3.0以后支持 | 可通过客户端实现 | 支持 |
| 高可用 | 支持 | 3.0以后支持 | 不支持,可通过第三方应用比如magent实现 | 支持 |
| 动态扩展 | 支持 | 3.0以后支持 | 可通过客户端实现 | 支持,本地存储在.data和.index文件 |
| 效率 | LDB < RDB < MDB | 高 | 高于redis | 高于memcache |
| 持久化 | LDB、RDB引擎支持 | 支持(AOF、默认RDB) | 不支持,可通过第三方应用实现 | 支持 |
| 缓存过期失效策略 | 支持 | 支持 | 支持,lru算法 | 支持,LRU(默认),FIFO,LFU |
| 数据结构 | K/V、list、hash、set、sortedsort等 | K/V、list、hash、set、sortedsort五种数据结构 | 支持简单的K/V结构 | 支持简单的K/V结构 |
| 分布式 | 支持 | 3.0以后支持 | 客户端使用一致性hash做分布式 | 支持 |
| 跨机房管理 | 支持 | 不支持 | 不支持 | 不支持 |
| 多集群管理 | 支持 | 不支持 | 不支持 | 不支持 |
| 使用状况 | 只有阿里内部大规模使用 | 普遍使用 | 使用情况较多 | 多用于hibernate的缓存实现 |
| 缺点 | 文档不全,社区不活跃,单节点上性能没有redis高,不能对key实现模糊查询,单条数据不能太大key建议1k以下,value不能超过1M,建议10k以下 | 3.0以前不支持集群,单线程无法充分利用多核服务器CPU,事务支持较弱,rdb每次都是写全量数据,成本高,aof追加导致log特别大 | 结构单一,数据在内存重启会丢失,数据大小受内存限制 | 结构单一、只适用于java体系,只能用java编写客户端,且使用磁盘做cache时占空间 |
| 优点 | 采用分布式集群架构,具备自动容灾及故障迁移能力,对存储层做了抽象,底层方便切换不同的存储引擎,采用一致性哈希算法将key分散在Q个桶中,并将桶放到不同的dataserver上,保证数据平衡,tair高可用比较强,容灾性比redis强,支持多种集群结构,支持跨机房数据分布 | 非常丰富的数据结构而且都是原子性操作、高速读写、支持事务,支持aof、rdb两种持久化机制,拥有丰富特性,订阅发布 Pub / Sub 功能、Key 过期策略、事务、支持多个 DB、计数、支持集群和数据备份 | 简洁,灵活,多线程非阻塞io效率高,所有支持多种语言api,且在并发下用cas保证一致性 | 效率高,功能强大,版本迭代特别快、缓存策略支持多种,可以通过rmi可插入api实现分布式缓存、具备缓存监听、支持多缓存实例、提供hibernate的缓存实现、支持非持久化和持久化缓存数据 |
5.3 Redis与Memcache的区别
redis支持更丰富的数据类型(支持更复杂的应用场景):Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。memcache支持简单的数据类型,String。Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而Memecache把数据全部存在内存之中。集群模式:memcached没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但是 redis 目前是原生支持 cluster 模式的.Redis使用单线程:Memcached是多线程,非阻塞IO复用的网络模型;Redis使用单线程的多路 IO 复用模型。

六、负载均衡
负载均衡是微服务架构中必须使用的技术,通过负载均衡来实现系统的高可用、集群扩容等功能。负载均衡可通过硬件设备及软件来实现,硬件比如:F5、Array等,软件比如:LVS、Nginx等。

用户请求先到达负载均衡器(也相当于一个服务),负载均衡器根据负载均衡算法将请求转发到微服务。负载均衡算法有:轮训、随机、加权轮训、加权随机、地址哈希等方法,负载均衡器维护一份服务列表,根据负载均衡算法将请求转发到相应的微服务上,所以负载均衡可以为微服务集群分担请求,降低系统的压力。
七、事务模式
7.1 四种事务模式对比

7.2 XA模式
XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准,XA 规范 描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对 XA 规范 提供了支持。
XA是规范,目前主流数据库都实现了这种规范,实现的原理都是基于两阶段提交。
正常情况:

异常情况:

一阶段:
- 事务协调者通知每个事物参与者执行本地事务
- 本地事务执行完成后报告事务执行状态给事务协调者,此时事务不提交,继续持有数据库锁
二阶段:
- 事务协调者基于一阶段的报告来判断下一步操作
- 如果一阶段都成功,则通知所有事务参与者,提交事务
- 如果一阶段任意一个参与者失败,则通知所有事务参与者回滚事务
7.3 AT模式
AT模式同样是分阶段提交的事务模型,不过缺弥补了XA模型中资源锁定周期过长的缺陷。
基本流程图:

阶段一RM的工作:
- 注册分支事务
- 记录undo-log(数据快照)
- 执行业务sql并提交
- 报告事务状态
阶段二提交时RM的工作:
- 删除undo-log即可
阶段二回滚时RM的工作:
- 根据undo-log恢复数据到更新前
1. AT与XA的区别
- XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。
- XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚。
- XA模式强一致;AT模式最终一致
2. 脏写问题
在多线程并发访问AT模式的分布式事务时,有可能出现脏写问题
解决思路:引入了全局锁的概念。在释放DB锁之前,先拿到全局锁。避免同一时刻有另外一个事务来操作当前数据。
3. 优缺点
AT模式的优点:
- 一阶段完成直接提交事务,释放数据库资源,性能比较好
- 利用全局锁实现读写隔离
- 没有代码侵入,框架自动完成回滚和提交
AT模式的缺点:
- 两阶段之间属于软状态,属于最终一致
- 框架的快照功能会影响性能,但比XA模式要好很多
7.4 TCC模式
TCC模式与AT模式非常相似,每阶段都是独立事务,不同的是TCC通过人工编码来实现数据恢复。需要实现三个方法:
- Try:资源的检测和预留;
- Confirm:完成资源操作业务;要求 Try 成功 Confirm 一定要能成功。
- Cancel:预留资源释放,可以理解为try的反向操作。
1. 事务架构
Seata中的TCC模型依然延续之前的事务架构,如图:

2.优缺点
TCC模式的每个阶段是做什么的?
- Try:资源检查和预留
- Confirm:业务执行和提交
- Cancel:预留资源的释放
TCC的优点是什么?
- 一阶段完成直接提交事务,释放数据库资源,性能好
- 相比AT模型,无需生成快照,无需使用全局锁,性能最强
- 不依赖数据库事务,而是依赖补偿操作,可以用于非事务型数据库
TCC的缺点是什么?
- 有代码侵入,需要人为编写try、Confirm和Cancel接口,太麻烦
- 软状态,事务是最终一致
- 需要考虑Confirm和Cancel的失败情况,做好幂等处理
3.事务悬挂和空回滚
1)空回滚
当某分支事务的try阶段阻塞时,可能导致全局事务超时而触发二阶段的cancel操作。在未执行try操作时先执行了cancel操作,这时cancel不能做回滚,就是空回滚。
如图:

执行cancel操作时,应当判断try是否已经执行,如果尚未执行,则应该空回滚。
2)业务悬挂
对于已经空回滚的业务,之前被阻塞的try操作恢复,继续执行try,就永远不可能confirm或cancel ,事务一直处于中间状态,这就是业务悬挂。
执行try操作时,应当判断cancel是否已经执行过了,如果已经执行,应当阻止空回滚后的try操作,避免悬挂
7.5 SAGA模式
Saga 模式是 Seata 即将开源的长事务解决方案,将由蚂蚁金服主要贡献。
其理论基础是Hector & Kenneth 在1987年发表的论文Sagas。
Seata官网对于Saga的指南:https://seata.io/zh-cn/docs/user/saga.html
1.原理
在 Saga 模式下,分布式事务内有多个参与者,每一个参与者都是一个冲正补偿服务,需要用户根据业务场景实现其正向操作和逆向回滚操作。
分布式事务执行过程中,依次执行各参与者的正向操作,如果所有正向操作均执行成功,那么分布式事务提交。如果任何一个正向操作执行失败,那么分布式事务会去退回去执行前面各参与者的逆向回滚操作,回滚已提交的参与者,使分布式事务回到初始状态。

Saga也分为两个阶段:
- 一阶段:直接提交本地事务
- 二阶段:成功则什么都不做;失败则通过编写补偿业务来回滚
2.优缺点
优点:
- 事务参与者可以基于事件驱动实现异步调用,吞吐高
- 一阶段直接提交事务,无锁,性能好
- 不用编写TCC中的三个阶段,实现简单
缺点:
软状态持续时间不确定,时效性差
没有锁,没有事务隔离,会有脏写
八、分布式事务
8.1 概念
在分布式系统下,一个业务跨越多个服务或数据源,每个服务都是一个分支事务,要保证所有分支事务最终状态一致,这样的事务就是分布式事务。
分布式事务,就是指不是在单个服务或单个数据库架构下,产生的事务,例如:
- 跨数据源的分布式事务
- 跨服务的分布式事务
- 综合情况
8.2 CAP定理
1998年,加州大学的计算机科学家 Eric Brewer 提出,分布式系统有三个指标。
Consistency(一致性)
用户访问分布式系统中的任意节点,得到的数据必须一致。
Availability(可用性)
用户访问集群中的任意健康节点,必须能得到响应,而不是超时或拒绝。
Partition tolerance (分区容错性)
因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接,形成独立分区。
在分布式系统中,系统间的网络不能100%保证健康,一定会有故障的时候,而服务有必须对外保证服务。因此Partition Tolerance不可避免。
当节点接收到新的数据变更时,就会出现问题了:
如果此时要保证一致性,就必须等待网络恢复,完成数据同步后,整个集群才对外提供服务,服务处于阻塞状态,不可用。
如果此时要保证可用性,就不能等待网络恢复,那node01、node02与node03之间就会出现数据不一致。
也就是说,在P一定会出现的情况下,A和C之间只能实现一个。
8.3 BASE理论
BASE理论是对CAP的一种解决思路,包含三个思想:
- Basically Available (基本可用):分布式系统在出现故障时,允许损失部分可用性,即保证核心可用。
- **Soft State(软状态):**在一定时间内,允许出现中间状态,比如临时的不一致状态。
- Eventually Consistent(最终一致性):虽然无法保证强一致性,但是在软状态结束后,最终达到数据一致。
8.4 解决分布式事务思路
分布式事务最大的问题是各个子事务的一致性问题,因此可以借鉴CAP定理和BASE理论,有两种解决思路:
AP模式:各子事务分别执行和提交,允许出现结果不一致,然后采用弥补措施恢复数据即可,实现最终一致。
CP模式:各个子事务执行后互相等待,同时提交,同时回滚,达成强一致。但事务等待过程中,处于弱可用状态。
但不管是哪一种模式,都需要在子系统事务之间互相通讯,协调事务状态,也就是需要一个事务协调者(TC);这里的子系统事务,称为分支事务;有关联的各个分支事务在一起称为全局事务。
九、服务保护技术对比
在SpringCloud当中支持多种服务保护技术:
早期比较流行的是Hystrix框架,但目前国内实用最广泛的还是阿里巴巴的Sentinel框架,这里我们做下对比:
| Sentinel | Hystrix | resilience4j | |
|---|---|---|---|
| 隔离策略 | 信号量隔离 | 线程池隔离/信号量隔离 | 信号量隔离 |
| 熔断降级策略 | 基于慢调用比例或异常比例 | 基于失败比率 | 基于异常比率、响应时间 |
| 实时指标实现 | 滑动窗口 | 滑动窗口(基于 RxJava) | Ring Bit Buffer |
| 规则配置 | 支持多种数据源 | 支持多种数据源 | 有限支持 |
| 扩展性 | 多个扩展点 | 插件的形式 | 接口的形式 |
| 基于注解的支持 | 支持 | 支持 | 支持 |
| 限流 | 基于 QPS,支持基于调用关系的限流 | 有限的支持 | Rate Limiter |
| 流量整形 | 支持慢启动、匀速排队模式 | 不支持 | 简单的 Rate Limiter模式 |
| 系统自适应保护 | 支持 | 不支持 | 不支持 |
| 控制台 | 开箱即用,可配置规则、查看秒级监控、机器发现等 | 不完善 | 不提供控制台,可对接其它监控系统 |
| 常见框架的适配 | Servlet、Spring Cloud、Dubbo、gRPC 等 | Servlet、Spring Cloud Netflix |
9.1 Sentinel的线程隔离与Hystix的线程隔离差别
Hystix默认是基于线程池实现的线程隔离,每一个被隔离的业务都要创建一个独立的线程池,线程过多会带来额外的CPU开销,性能一般,但是隔离性更强。
Sentinel是基于信号量(计数器)实现的线程隔离,不用创建线程池,性能较好,但是隔离性一般。
十、流控技术对比
10.1 Sentinel的限流与Gateway的限流差别
限流算法常见的有三种实现:滑动时间窗口、令牌桶算法、漏桶算法。Gateway则采用了基于Redis实现的令牌桶算法。
而Sentinel内部却比较复杂:
- 默认限流模式是基于滑动时间窗口算法
- 排队等待的限流模式则基于漏桶算法
- 而热点参数限流则是基于令牌桶算法
十一、架构发展对比
从单机小型机时代-》垂直拆分-》集群化负载均衡-》服务化改造-》服务治理-》微服务时代-》服务网格
11.1 微服务时代
微服务时代有了Spring Cloud就完美了吗?不妨想一想会有哪些问题?
(1)最初是为了业务而写代码,比如登录功能、支付功能等,到后面会发现要解决网络通信的问题,虽然有 Spring Cloud里面的组件帮我们解决了,但是细想一下它是怎么解决的?在业务代码里面加上spring cloud maven依赖,加上spring cloud组件注解,写配置,打成jar的时候还必须要把非业务的代码也要融合在一起,称为“侵入式框架”;
(2)微服务中的服务支持不同语言开发,也需要维护不同语言和非业务代码的成本;
(3)业务代码开发者应该把更多的精力投入到业务熟悉度上,而不应该是非业务上,Spring Cloud虽然能解决微服务领域的很多问题,但是学习成本还是较大的;
(4)互联网公司产品的版本升级是非常频繁的,为了维护各个版本的兼容性、权限、流量等,因为Spring
Cloud是“代码侵入式的框架”,这时候版本的升级就注定要让非业务代码一起,一旦出现问题,再加上多语言之间的调用,工程师会非常痛苦;
(5)其实我们到目前为止应该感觉到了,服务拆分的越细,只是感觉上轻量级解耦了,但是维护成本却越高了,那么怎么 办呢?
我们不是说spring cloud不好,只是为了引出service mesh, 目前spring cloud微服务还是比较主流的, 我们指出spring cloud的不好也只是为了突出service mesh的优点
问题解决思路
本质上是要解决服务之间通信的问题,不应该将非业务的代码融合到业务代码中
也就是从客户端发出的请求,要能够顺利到达对应的服务,这中间的网络通信的过程要和业务代码尽量无关
服务通信无非就是服务发现、负载均衡、版本控制等等
- 在很早之前的单体架构中,其实通信问题也是需要写在业务代码中的,那时候怎么解决的呢?
解决方案:把网络通信,流量转发等问题放到了计算机网络模型中的TCP/UDP层,也就是非业务功能代码下沉,把这些网络的问题下沉到计算机网络模型当中,也就是网络七层模型
网络七层模型:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层
思考:
我们是否也可以把每个服务配置一个代理,所有通信的问题都交给这个代理去做,就好比大家熟悉的nginx,haproxy其实它们做反向代理把请求转发给其他服务器,也就为 Service Mesh的诞生和功能实现提供了一个解决思路
11.2 SideCar
它降低了与微服务架构相关的复杂性,并且提供了负载平衡、服务发现、流量管理、电路中断、遥测、故障注入等功能特性。
Sidecar模式是一种将应用功能从应用本身剥离出来作为单独进程的方式。该模式允许我们向应用无侵入添加多种功能,避免了为满足第三方组件需求而向应用添加额外的配置代码。
很多公司借鉴了Proxy模式,推出了Sidecar的产品,比如像Netflix的Prana,蚂蚁金服的SofaMesh

服务业务代码与Sidecar绑定在一起,每个服务都配置了一个Sidecar代理,每个服务所有的流量都经过sidecar,sidecar帮我们屏蔽了通信的细节,我的业务开发人员只需要关注业务就行了,而通信的事情交给sidecar处理 总结:可以理解成是代理,控制了服务的流量的进出,sidecar是为了通用基础设施而设计,可以做到与公司框架技术无侵入性
11.3 Linkerd
2016年1月,离开Twitter的基础设施工程师打造的一个服务网格项目,第一个Service Mesh项目由此诞生,解决通用性。 Linkerd很好地结合了Kubernetes所提供的功能,以此为基础,在每个Kubernetes Node上都部署运行一个Linkerd实例,用代理的方式将加入Mesh的Pod通信转接给Linkerd,这样Linkerd就能在通信链路中完成对通信的控制和监控。
Linkerd设计思想

Linderd的思想跟sidecar很类似,目标也是屏蔽网络通信细节 Linkerd除了完成对Service Mesh的命名,以及Service Mesh各主要功能的落地,还有以下重要创举:
无须侵入工作负载的代码,直接进行通信监视和管理;
提供了统一的配置方式,用于管理服务之间的通信和边缘通信;
除了支持Kubernetes,还支持多种底层平台。
总结:
跟我们前面sidecar很类似,以前的调用方式都是服务来调用服务,在Linkerd思想要求所有的流量都走sidecar,Linkerd帮业务人员屏蔽了通信细节,通信不需要侵入到业务代码内部了,这样业务开发者就专注于业务开发的本身
Linkerd在面世之后,迅速获得用户的关注,并在多个用户的生产环境上成功部署、运行。2017年,Linkerd加入CNCF,随后宣布完成对千亿次生产环境请求的处理,紧接着发布了1.0版本,并且具备一定数量的商业用户,一时间风光无限,一直持续到Istio横空出世。
问题:
在早期的时候又要部署服务,又要部署sidecar,对于运维人员来说比较困难的,所以没有得到很好的发展,其实主要的 问题是Linkerd只是实现了数据层面的问题,但没有对其进行很好的管理。
数据层面:通过sidecar解决了数据处理的问题
11.4 istio
由Google、IBM和Lyft共同发起的开源项目
Istio makes it easy to create a network of deployed services with load balancing, service-to-service authentication, monitoring, and more, with few or no code changes in service code. You add Istio support to services by deploying a special sidecar proxy throughout your environment that intercepts all network communication between microservices, then configure and manage Istio using its control plane functionality
翻译:
通过Istio,可以轻松创建带有负载平衡,服务到服务的身份验证,监视等功能的已部署服务网络,使得服务中的代码更改很少或没有更改。 通过在整个环境中部署一个特殊的sidecar代理来拦截微服务之间的所有网络通信,然后使用其控制平面功能配置和管理,可以为服务添加Istio支持。什么是控制平面?
控制平面就是来管理数据平面,也就是管理sideCar
所以istio既有数据平面也有控制平面
istio能干什么?
1.HTTP、gRPC、WebSocket和TCP流量的自动负载平衡。 2.路由、重试、故障转移和故障注入对流量行为进行细粒度控制。 3.支持访问控制、速率限制、配置API。 4.集群内所有流量的自动衡量、日志和跟踪,包括集群入口和出口。 5.使用基于身份验证和授权来保护集群中服务跟服务之间的通信。 **总结:很明显Istio不仅拥有“数据平面(Data Plane)”,而且还拥有“控制平面(Control Plane),也就是拥有了数据 接管与集中控制能力。
11.5 服务网格
服务网格:指的是微服务网络应用之间的交互,随着规模和复杂性增加,服务跟服务调用错综复杂 如下图所示

如果每一个格子都是一个sidecar数据平面,然后sidecar进行彼此通信,那么servicemech就是来管理每个格子的控制平面,这就是服务网格,从架构层面看起来跟网格很像
特点:
基础设施:服务网格是一种处理服务之间通信的基础设施层。
支撑云原生:服务网格尤其适用于在云原生场景下帮助应用程序在复杂的服务间可靠地传递请求。
网络代理:在实际使用中,服务网格一般是通过一组轻量级网络代理来执行治理逻辑的。
对应用透明:轻量网络代理与应用程序部署在一起,但应用感知不到代理的存在,还是使用原来的方式工作。
11.6 什么是Service Mesh
istio官网 也对什么是service mesh给出了定义
地址:https://istio.io/docs/concepts/what-is-istio/#what-is-a-service-mesh
Istio addresses the challenges developers and operators face as monolithic applications transition towards a distributed microservice architecture. To see how, it helps to take a more detailed look at Istio’s service mesh.
翻译:
解决开发与运维部署分布式微服务面临的问题
The term service mesh is used to describe the network of microservices that make up such applications and the interactions between them. As a service mesh grows in size and complexity, it can become harder to understand and manage. Its requirements can include discovery, load balancing, failure recovery, metrics, and monitoring. A service mesh also often has more complex operational requirements, like A/B testing, canary rollouts, rate limiting, access control, and end-to-end authentication.
翻译:
也是解决微服务之间服务跟服务之间通信的问题,可以包括服务发现、负载平衡、故障恢复、度量和监视,服务网格通常还具有更复杂的操作需求,如A/B测试、速率限制、访问控制和端到端身份验证
11.7 CNCF云原生组织发展和介绍
云原生发展历史时间轴

- 微服务
马丁大师在2014年定义了微服务
- Kubernetes
从2014年6月由Google宣布开源,到2015年7月发布1.0这个正式版本并进入CNCF基金会,再到2018年3月从CNCF基金会正式毕业,迅速成为容器编排领域的标准,是开源历史上发展最快的项目之一
- Linkerd
Scala语言编写,运行在JVM中,Service Mesh名词的创造者
2016年01月15号,0.0.7发布
2017年01月23号,加入CNCF组织
2017年04月25号,1.0版本发布
- Envoy
envoy是一个开源的服务代理,为云原生设计的程序,由C++语言编程[Lyft]
2016年09月13号,1.0发布
2017年09月14号,加入CNCF组织
- Istio
Google、IBM、Lyft发布0.1版本
Istio是开源的微服务管理、保护和监控框架。Istio为希腊语,意思是”起航“。
CNCF介绍
CNCF 是一个开源软件基金会,致力于使云原生计算具有普遍性和可持续性。 云原生计算使用开源软件技术栈将应用程序部署为微服务,将每个部分打包到自己的容器中,并动态编排这些容器以优化资源利用率。 云原生技术使软件开发人员能够更快地构建出色的产品。
CNCF解决了什么问题
统一基础平台:kubernetes
如果我们需要日志监控:Prometheus
需要代理:Envoy
需要分布式链路跟踪:Jaeger
......
介绍几个常用的已经毕业的云原生项目
- Kubernetes
Kubernetes 是世界上最受欢迎的容器编排平台也是第一个 CNCF 项目。 Kubernetes 帮助用户构建、扩展和管理应用程序及其动态生命周期。
- Prometheus
Prometheus 为云原生应用程序提供实时监控、警报包括强大的查询和可视化能力,并与许多流行的开源数据导入、导出工具集成。
- Jaeger
Jaeger 是由 Uber 开发的分布式追踪系统,用于监控其大型微服务环境。 Jaeger 被设计为具有高度可扩展性和可用性,它具有现代 UI,旨在与云原生系统(如 OpenTracing、Kubernetes 和 Prometheus)集成。
- Containerd
Containerd 是由 Docker 开发并基于 Docker Engine 运行时的行业标准容器运行时组件。 作为容器生态系统的选择,Containerd 通过提供运行时,可以将 Docker 和 OCI 容器镜像作为新平台或产品的一部分进行管理。
- Envoy
Envoy 是最初在 Lyft 创建的 Service Mesh(服务网格),现在用于Google、Apple、Netflix等公司内部。 Envoy 是用 C++ 编写的,旨在最大限度地减少内存和 CPU 占用空间,同时提供诸如负载均衡、网络深度可观察性、微服务环境中的跟踪和数据库活动等功能。
- Fluentd
Fluentd 是一个统一的日志记录工具,可收集来自任何数据源(包括数据库、应用程序服务器、最终用户设备)的数据,并与众多警报、分析和存储工具配合使用。 Fluentd 通过提供一个统一的层来帮助用户更好地了解他们的环境中发生的事情,以便收集、过滤日志数据并将其路由到许多流行的源和目的地。
孵化中的项目,
- Open Tracing
OpenTracing:为不同的平台,供应中立的API,使开发人员可以轻松地应用分布式跟踪。
- GRPC
gRPC 是一个高性能、开源和通用的 RPC 框架,语言中立,支持多种语言。
- CNI
CNI 就是这样一个标准,它旨在为容器平台提供网络的标准化。不同的容器平台能够通过相同的接口调用不同的网络组件。
- Helm
Helm 是 Kubernetes 的包管理器。包管理器类似于我们在Centos中使用的yum一样,能快速查找、下载和安装软件包。
- Etcd
一个高可用的分布式键值(key-value)数据库。etcd内部采用raft协议作为一致性算法,etcd基于Go语言实现。一般用的最多的就是作为一个注册中心来使用
11.8 国内兴起的服务网格
前面提到,在Service Mesh这个概念得到具体定义之前,实际上已经有很多厂商开始了微服务新的尝试,这一动作势必引发对微服务治理的强劲需求。在Service Mesh概念普及之后,有的厂商意识到自身产品也具备Service Mesh的特点,也有厂商受其启发,将自有的服务治理平台进行完善和改造,推出自己的Service Mesh产品。例如,蚂蚁金服、腾讯和华为都推出自己的网格产品,华为的产品甚至已被投入公有云进行商业应用。
- 蚂蚁金服 sofa Mesh
代理架构

前身是SOFA RPC ,2018年07月正式开源
- 腾讯 Tencent Service Mesh
代理架构

- 华为 CSE Mesher
代理架构

总结: 基本上都借鉴了Sidecar、Envoy和Istio等设计思想
十二、APM系统对比
APM (Application Performance Management) 即应用性能管理系统,是对企业系统即时监控以实现对应用程序性能管理和故障管理的系统化的解决方案。应用性能管理,主要指对企业的关键业务应用进行监测、优化,提高企业应用的可靠性和质量,保证用户得到良好的服务,降低IT总拥有成本。APM系统是可以帮助理解系统行为、用于分析性能问题的工具,以便发生故障的时候,能够快速定位和解决问题。
12.1 Open Tracing
OpenTracing通过提供平台无关、厂商无关的API,使得开发人员能够方便的添加(或更换)追踪系统的实现。OpenTracing中最核心的概念就是Trace。
Trace
在广义上,一个trace代表了一个事务或者流程在(分布式)系统中的执行过程。在OpenTracing标准中,trace是多个span组成的一个有向无环图(DAG),每一个span代表trace中被命名并计时的连续性的执行片段 例如客户端发起的一次请求,就可以认为是一个Trace
Span
一个Span代表系统中具有开始时间和执行时长的逻辑运行单元。span之间通过嵌套或者顺序排列建立逻辑因果关系。 Span里面的信息包括:操作的名字,开始时间和结束时间,可以附带多个 key:value 构成的 Tags(key必须是String,value可以是 String, bool 或者数字),还可以附带 Logs 信息(不一定所有的实现都支持)也是 key:value形式。 一个span可以和一个或者多个span间存在因果关系。OpenTracing定义了两种关系: ChildOf 和 FollowsFrom 。这两种引用类型代表了子节点和父节点间的直接因果关系。未来,OpenTracing将支持非因果关系的span引用关系。(例如:多个span被批量处理,span在同一个队列中,等等) ChildOf 很好理解,就是父亲 Span 依赖另一个孩子 Span。比如函数调用,被调者是调用者的孩子,比如说 RPC 调用,服务端那边的Span,就是 ChildOf 客户端的。很多并发的调用,然后将结果聚合起来的操作,就构成了 ChildOf 关系。 如果父亲 Span 并不依赖于孩子 Span 的返回结果,这时可以说它他构成 FollowsFrom 关系。
Log
每个span可以进行多次Logs操作,每一次Logs操作,都需要一个带时间戳的时间名称,以及可选的任意大小的存储结构
Tags
每个span可以有多个键值对(key:value)形式的Tags,Tags是没有时间戳的,支持简单的对span进行注解和补充。 Tags的详细信息,其中记录了数据库访问的SQL语句等内容
12.2 分布式链路追踪
随着分布式系统和微服务架构的出现,一次用户的请求会经过多个系统,不同服务之间的调用关系十分复杂,任何一个系统出错都可能影响整个请求的处理结果。以往的监控系统往往只能知道单个系统的健康状况、一次请求的成功失败,无法快速定位失败的根本原因。
性能分析:一个服务依赖很多服务,被依赖的服务也依赖了其他服务。如果某个接口耗时突然变长了,那未必是直接调用的下游服务慢了,也可能是下游的下游慢了造成的,如何快速定位耗时变长的根本原因呢? 链路梳理:需求迭代很快,系统之间调用关系变化频繁,靠人工很难梳理清楚系统链路拓扑(系统之间的调用关系)。 为了解决这些问题,Google 推出了一个分布式链路跟踪系统 Dapper ,之后各个互联网公司都参照Dapper 的思想推出了自己的分布式链路跟踪系统,而这些系统就是分布式系统下的APM系统。 分布式链路追踪(Distributed Tracing),就是将一次分布式请求还原成调用链路,进行日志记录,性能监控并将一次分布式请求的调用情况集中展示。比如各个服务节点上的耗时、请求具体到达哪台机器上、每个服务节点的请求状态等等
12.3 主流的开源APM产品
PinPoint
Pinpoint是由一个韩国团队实现并开源,针对Java编写的大规模分布式系统设计,通过JavaAgent的机制做字节代码植入,实现加入traceid和获取性能数据的目的,对应用代码零侵入。特点是支持多种插件,UI功能强大,接入端无代码侵入。官网
SkyWalking
SkyWalking是apache基金会下面的一个开源APM项目,为微服务架构和云原生架构系统设计。它通过探针自动收集所需的指标,并进行分布式追踪。通过这些调用链路以及指标,Skywalking APM会感知应用间关系和服务间关系,并进行相应的指标统计。Skywalking支持链路追踪和监控应用组件基本涵盖主流框架和容器,如国产RPC Dubbo和motan等,国际化的spring boot,spring cloud。接入端无代码侵入。官方网站
Zipkin
Zipkin是由Twitter开源,是分布式链路调用监控系统,聚合各业务系统调用延迟数据,达到链路调用监控跟踪。Zipkin基于Google的Dapper论文实现,主要完成数据的收集、存储、搜索与界面展示。该产品结合spring-cloud-sleuth使用较为简单, 集成很方便, 但是功能较简单。官方网站
CAT
CAT是由大众点评开源的项目,基于Java开发的实时应用监控平台,包括实时应用监控,业务监控,可以提供十几张报表展示。集成方案是通过代码埋点的方式来实现监控,比如: 拦截器,过滤器等。 对代码的侵入性很大,集成成本较高。风险较大。官方网站
Sleuth
SpringCloud 提供的分布式系统中链路追踪解决方案